import { ipcMain, BrowserWindow } from 'electron'

class IpcRelayService {
  constructor() {
    this.init()
  }

  init() {
    ipcMain.on('cross-window-message', (event, message) => {
      this.relayMessage(event, message)
    })

    ipcMain.handle('cross-window-invoke', async (event, message) => {
      return await this.relayInvoke(event, message)
    })
  }

  // 单向消息转发
  relayMessage(event, message) {
    const { targetWindowId, channel, data } = message
    const senderWindow = BrowserWindow.fromWebContents(event.sender)

    this.getTargetWindows(event.sender, targetWindowId).forEach((window) => {
      window?.webContents.send(`cross-window-${channel}`, {
        senderWindowId: senderWindow?.id,
        data
      })
    })
  }

  // 双向通信（带回复）
  async relayInvoke(event, message) {
    const { targetWindowId, channel, data } = message
    const senderWindow = BrowserWindow.fromWebContents(event.sender)
    const targetWindows = this.getTargetWindows(event.sender, targetWindowId)

    // 1. 发送请求到目标窗口
    targetWindows.forEach((window) => {
      window?.webContents.send(`cross-window-${channel}-request`, {
        senderWindowId: senderWindow?.id,
        data
      })
    })

    // 2. 等待所有目标窗口回复
    const replies = await Promise.all(
      targetWindows.map((window) => {
        return new Promise((resolve) => {
          const replyChannel = `cross-window-${channel}-reply-${window?.id}`

          // 监听目标窗口的回复
          ipcMain.once(replyChannel, (_, reply) => {
            resolve(reply)
          })

          // 要求目标窗口发送回复
          window?.webContents.send(`cross-window-${channel}-listen`, {
            replyChannel,
            timeout: 5000 // 超时时间
          })
        })
      })
    )

    // 3. 合并有效回复
    return replies.filter((reply) => reply !== undefined)
  }

  // 获取有效目标窗口
  getTargetWindows(senderWebContents, targetWindowId) {
    return (
      targetWindowId
        ? [BrowserWindow.fromId(targetWindowId)].filter(Boolean)
        : BrowserWindow.getAllWindows()
    ).filter((window) => !window?.isDestroyed() && window?.webContents.id !== senderWebContents.id)
  }
}

export default new IpcRelayService()
